package main

import (
	"encoding/json"
	"fmt"
	"log"
	"purchase-mall/conf"
	"purchase-mall/dao/pg"
	"purchase-mall/dao/redis"
	"purchase-mall/logger"
	"purchase-mall/models"
	"purchase-mall/services"
	"purchase-mall/utils"
	"time"

	"github.com/robfig/cron/v3"
	"go.uber.org/zap"
)

var jsonStr = `[{
    "namespace": "acs_kafka",
    "metric_name": {
        "instance_disk_capacity": "Maximum",
        "instance_message_num_input": "Value",
        "instance_message_input": "Value",
        "instance_message_output": "Value",
        "instance_reqs_input": "Value",
        "instance_reqs_output": "Value"
    },
    "dimensions": "[{\"instanceId\": \"alikafka_post-cn-7pp2tik4j014\"}]"
},{
    "namespace": "acs_kvstore",
    "metric_name": {
        "CpuUsage": "Maximum",
        "MemoryUsage": "Maximum",
        "IntranetIn": "Maximum",
        "IntranetOut": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"r-2zeek1nfwsaojl1pty\"}]"
},{
    "namespace": "acs_cdn",
    "metric_name": {
        "BPS": "Maximum",
        "QPS": "Maximum",
        "InternetOut": "Maximum",
        "l1_acc": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"tiles1.geovisearth.com\"}]"
},{
    "namespace": "acs_cdn",
    "metric_name": {
        "BPS": "Maximum",
        "QPS": "Maximum",
        "InternetOut": "Maximum",
        "l1_acc": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"tiles2.geovisearth.com\"}]"
},{
    "namespace": "acs_slb_dashboard",
    "metric_name": {
        "TrafficRXNew": "Maximum",
        "TrafficTXNew": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"lb-2ze0mn9pqxqaa3rqo0sp5\"}]"
},{
    "namespace": "acs_slb_dashboard",
    "metric_name": {
        "TrafficRXNew": "Maximum",
        "TrafficTXNew": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"lb-2zek8bddomdrjhl7tyc2t\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
        "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum",
        "read_ops": "Maximum",
        "write_ops": "Maximum"
    },
    "dimensions": "[{\"instanceId\":\"ld-2zes027963sv5xp96\",\"host\":\"lindormtable-1\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
          "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum",
        "read_ops": "Maximum",
        "write_ops": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\",\"host\": \"lindormtable-2\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
          "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum",
        "read_ops": "Maximum",
        "write_ops": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\",\"host\": \"lindormtable-3\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
        "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\",\"host\": \"master1-1\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
        "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\",\"host\": \"master2-1\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
        "cpu_user": "Maximum",
        "mem_used_percent": "Maximum",
        "bytes_in": "Maximum",
        "bytes_out": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\",\"host\": \"master3-1\"}]"
},{
    "namespace": "acs_lindorm",
    "metric_name": {
        "storage_total_bytes": "Maximum",
        "storage_used_bytes": "Maximum",
        "storage_used_percent": "Maximum"
    },
    "dimensions": "[{\"instanceId\": \"ld-2zes027963sv5xp96\"}]"
}]`

func newWithSeconds() *cron.Cron {
	secondParser := cron.NewParser(
		cron.SecondOptional | cron.Minute | cron.Hour |
			cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
	)
	return cron.New(cron.WithParser(secondParser), cron.WithChain())
}

// TimerHandleTile 处理瓦片访问量接口
func TimerHandleTile() {
	//服务层获取接口
	timeStart, timeEnd := utils.TileTimer() //获取定时任务时间
	err, _ := services.MetricTile(timeStart, timeEnd)
	if err != nil {
		zap.L().Error("services.MetricTile() failed", zap.Error(err))
		return
	}
}

// TimerHandleTileForDoris 处理瓦片访问量接口
func TimerHandleTileForDoris() {
	//服务层获取接口
	timeStart, timeEnd := utils.TileTimer() //获取定时任务时间
	err, _ := services.MetricTileDoris(timeStart, timeEnd)
	if err != nil {
		zap.L().Error("services.MetricTileDoris() failed", zap.Error(err))
		return
	}
}

// TimerHandleAli 处理阿里云metric阈值
func TimerHandleAli() {
	var params []map[string]interface{}
	errJson := json.Unmarshal([]byte(jsonStr), &params)
	if errJson != nil {
		fmt.Printf("error is %v\n", errJson)
		return
	}
	//获取定时任务时间
	timeStart, timeEnd := utils.MetricTimer()
	//fmt.Printf("timeStart:%s,timeEnd:%s", timeStart, timeEnd)

	//var AliParam models.AliParam
	for _, param := range params {
		//fmt.Println(param["namespace"])
		param["period"] = "60"
		param["start_time"] = timeStart
		param["end_time"] = timeEnd

		for metric, maxValue := range param["metric_name"].(map[string]interface{}) {
			//直接转换好像只支持string
			//err := mapstructure.Decode(param, &AliParam)
			//if err != nil {
			//	fmt.Println("mapstructure.Decode", err.Error())
			//}
			//fmt.Printf("AliParam %+v\n", AliParam)

			AliParam := &models.AliParam{
				Namespace:  param["namespace"].(string),
				MetricName: param["metric_name"].(map[string]interface{}), //这块可以不要
				Period:     param["period"].(string),
				StartTime:  param["start_time"].(string),
				EndTime:    param["end_time"].(string),
				Dimensions: param["dimensions"].(string),
			}
			//err, res := services.KafkaMetric(AliParam, metric, maxValue.(string))
			err, _ := services.AliMetric(AliParam, metric, maxValue.(string))
			if err != nil {
				zap.L().Error("services.AliMetric() failed", zap.Error(err))
				return
			}
			//fmt.Printf("Aliyun API res %+v\n", res)
		}
		//fmt.Printf("%v: %+v\n", param["namespace"], param)
	}

}

func main() {
	// 加载配置
	if err := conf.Init(); err != nil {
		fmt.Printf("load config failed, err:%v\n", err)
		return
	}
	if err := logger.Init(conf.Conf.LogConfig, conf.Conf.Mode); err != nil {
		fmt.Printf("init logger failed, err:%v\n", err)
		return
	}

	//连接PostgreSQl
	if err := pg.Init(conf.Conf.PgConfig); err != nil {
		fmt.Printf("init pg failed, err:%v\n", err)
		return
	}
	//defer pg.Close() // 程序退出关闭数据库连接

	//连接Redis
	if err := redis.Init(conf.Conf.RedisConfig); err != nil {
		fmt.Printf("init redis failed, err:%v\n", err)
		return
	}
	//defer redis.Close()

	//定时任务处理
	log.Println("[Cron] Starting...")
	c := newWithSeconds()
	//spec := "*/10 * * * * *" //每5秒执行一次
	spec := "0 0 1 * * ?" //每天凌晨1点钟执行
	//spec := "0 39 17 * * ?" //修复数据指定时间

	//获取阿里metric
	c.AddFunc(spec, func() {
		log.Println("[Cron] Run TimerHandleAli...")
		start := time.Now()
		TimerHandleAli()
		cost := time.Since(start)
		fmt.Printf("Get Ali Metirc cost=[%s]\n", cost)
	})

	//获取瓦片访问总数 ts版本v1 暂不用
	//c.AddFunc(spec, func() {
	//	log.Println("[Cron] Run TimerHandleTile...")
	//	start := time.Now()
	//	TimerHandleTile()
	//	cost := time.Since(start)
	//	fmt.Printf("Get Tile Total cost=[%s]\n", cost)
	//})

	//获取瓦片访问总数 Doris
	c.AddFunc(spec, func() {
		log.Println("[Cron] Run TimerHandleTileForDoris...")
		start := time.Now()
		TimerHandleTileForDoris()
		cost := time.Since(start)
		fmt.Printf("Get Tile Total cost=[%s]\n", cost)
	})

	c.Start()
	select {}

}
